import { CoordinateConverter, calculateDistance } from './coordinate';

// 定位配置
const LOCATION_CONFIG = {
  type: 'gps', // 使用纯GPS定位模式
  interval: 5000, // 定位间隔5秒
  distanceThreshold: 10 // 移动距离阈值10米
};

/**
 * 位置服务类
 * 处理GPS定位、监听和坐标转换
 */
export class LocationService {
  private watchId: number | null = null;
  private lastPosition: MapTypes.Coordinate | null = null;
  private reconnectTimer: number | null = null;
  
  /**
   * 开始GPS定位跟踪
   * @param onLocationUpdate 位置更新回调
   * @param onError 错误回调
   */
  startLocationTracking(
    onLocationUpdate: (position: MapTypes.Coordinate) => void,
    onError?: (error: MapTypes.LocationError) => void
  ): void {
    try {
      // 停止之前的监听
      this.stopLocationTracking();
      
      // 开始监听位置变化
      uni.startLocationUpdate({
        type: LOCATION_CONFIG.type,
        interval: LOCATION_CONFIG.interval,
        success: () => {
          console.log('GPS定位已启动');
          
          // 监听位置变化
          uni.onLocationChange((res: any) => {
            const gpsCoord: MapTypes.Coordinate = {
              lng: res.longitude,
              lat: res.latitude
            };
            
            // 转换为百度坐标
            const bdCoord = CoordinateConverter.wgs84ToBd09(gpsCoord.lng, gpsCoord.lat);
            
            // 计算与上次位置的距离
            if (this.lastPosition) {
              const distance = calculateDistance(bdCoord, this.lastPosition);
              
              // 如果移动距离小于阈值，则忽略此次更新
              if (distance < LOCATION_CONFIG.distanceThreshold) {
                return;
              }
            }
            
            // 更新上次位置
            this.lastPosition = bdCoord;
            
            // 调用位置更新回调
            onLocationUpdate(bdCoord);
          });
          
          // 监听位置错误
          uni.onLocationChangeError((error: any) => {
            console.error('GPS定位错误:', error);
            
            if (onError) {
              onError({
                errCode: error.errCode,
                errMsg: error.errMsg
              });
            }
            
            // 处理GPS信号丢失的情况
            if (error.errCode === 2) {
              this.handleGpsSignalLost(onLocationUpdate, onError);
            }
          });
        },
        fail: (err: any) => {
          console.error('启动GPS定位失败:', err);
          if (onError) {
            onError({
              errCode: -1,
              errMsg: '启动GPS定位失败: ' + err.errMsg
            });
          }
        }
      });
    } catch (error: any) {
      console.error('位置服务异常:', error);
      if (onError) {
        onError({
          errCode: -2,
          errMsg: '位置服务异常: ' + error.message
        });
      }
    }
  }
  
  /**
   * 停止GPS定位跟踪
   */
  stopLocationTracking(): void {
    try {
      // 停止位置更新
      uni.stopLocationUpdate({
        success: () => console.log('GPS定位已停止'),
        fail: (err) => console.error('停止GPS定位失败:', err)
      });
      
      // 清除位置变化监听
      uni.offLocationChange();
      uni.offLocationChangeError();
      
      // 清除重连定时器
      if (this.reconnectTimer !== null) {
        clearTimeout(this.reconnectTimer);
        this.reconnectTimer = null;
      }
      
      this.watchId = null;
    } catch (error) {
      console.error('停止位置服务异常:', error);
    }
  }
  
  /**
   * 获取当前位置（单次定位）
   * @returns Promise<MapTypes.Coordinate>
   */
  getCurrentPosition(): Promise<MapTypes.Coordinate> {
    return new Promise((resolve, reject) => {
      uni.getLocation({
        type: LOCATION_CONFIG.type,
        success: (res) => {
          const gpsCoord: MapTypes.Coordinate = {
            lng: res.longitude,
            lat: res.latitude
          };
          
          // 转换为百度坐标
          const bdCoord = CoordinateConverter.wgs84ToBd09(gpsCoord.lng, gpsCoord.lat);
          resolve(bdCoord);
        },
        fail: (err) => {
          console.error('获取位置失败:', err);
          reject(err);
        }
      });
    });
  }
  
  /**
   * 处理GPS信号丢失
   * @param onLocationUpdate 位置更新回调
   * @param onError 错误回调
   */
  private handleGpsSignalLost(
    onLocationUpdate: (position: MapTypes.Coordinate) => void,
    onError?: (error: MapTypes.LocationError) => void
  ): void {
    // 显示提示
    uni.showToast({
      title: 'GPS信号弱，请移动到开阔区域',
      icon: 'none',
      duration: 3000
    });
    
    // 如果有最后位置，存储到本地
    if (this.lastPosition) {
      uni.setStorageSync('LAST_KNOWN_POSITION', this.lastPosition);
    }
    
    // 尝试每30秒自动重连
    this.reconnectTimer = setTimeout(() => {
      console.log('尝试重新连接GPS...');
      this.startLocationTracking(onLocationUpdate, onError);
    }, 30000) as unknown as number;
  }
  
  /**
   * 获取最后已知位置
   * @returns MapTypes.Coordinate | null
   */
  getLastKnownPosition(): MapTypes.Coordinate | null {
    try {
      // 尝试从内存中获取
      if (this.lastPosition) {
        return this.lastPosition;
      }
      
      // 尝试从存储中获取
      const storedPosition = uni.getStorageSync('LAST_KNOWN_POSITION');
      if (storedPosition) {
        return storedPosition as MapTypes.Coordinate;
      }
      
      return null;
    } catch (error) {
      console.error('获取最后已知位置失败:', error);
      return null;
    }
  }
} 